#ifndef svl_TVariant_H
#define svl_TVariant_H

#include "svl.h"
#include "svl_TDateTime.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

namespace svl {

////////////////////////////////////////////////////////////////////////////////

struct TVariant : public svl::TArray_Object
{
  enum EType
  {
    EType_Null,
    EType_Bool,
    EType_Integer,
    EType_String,
    EType_Double,
    EType_DateTime,
    EType_Mem,
    EType_Object,
    EType_Pointer
  };
  EType GetEType() const { return type;}
  //
  TVariant()                    { type = EType_Null; Delete();}
  TVariant(const TVariant &V)   { type = EType_Null; *this = V;}
  TVariant(bool V)              { type = EType_Null; *this = V;}
  TVariant(int V)               { type = EType_Null; *this = V;}
  TVariant(double V)            { type = EType_Null; *this = V;}
  TVariant(svl::TString V)      { type = EType_Null; *this = V;}
  TVariant(const svl::TMem &V)  { type = EType_Null; *this = V;}
  TVariant(const TObject &V)    { type = EType_Null; *this = V;}
  TVariant(TPointer *V)         { type = EType_Null; *this = V;}
  TVariant(char *V)             { type = EType_Null; *this = V;}
  TVariant(TDateTime V)         { type = EType_Null; *this = V;}
 ~TVariant()                    { Delete();}
  //
  void SetNull() { Delete(); type = EType_Null;}
  bool  IsNull() { return type == EType_Null;}
  //
  TVariant &operator = (const TVariant &V);
  TVariant &operator = (bool V);
  TVariant &operator = (int V);
  TVariant &operator = (double V);
  TVariant &operator = (svl::TString V);
  TVariant &operator = (const svl::TMem &V);
  TVariant &operator = (const TObject &V);
  TVariant &operator = (TPointer *V);
  TVariant &operator = (char *V);
  TVariant &operator = (TDateTime V);
  //
  bool         Bool()     { return *this;}
  int          Integer()  { return *this;}
  double       Double()   { return *this;}
  svl::TMem   &Mem()      { return *this;}
  TObject     &Object()   { return *this;}
  TPointer    *Pointer()  { return *this;}
  svl::TString String()   { return *this;}
  TDateTime    DateTime() { return *this;}
  //
  operator bool();
  operator int();
  operator double();
  operator svl::TString();
  operator svl::TMem&();
  operator TObject&();
  operator TPointer*();
  operator TDateTime();
  //
  TString GetInfo();
  virtual TInfoParam AddInfoTo(TInfoParam Info);

  //
  //virtual TObject *NewInstance() { return new TVariant();}
  //virtual void CopyFrom(TObject *P) { *this = *(TVariant*)P;}
//TVariant *Value;
  //
  //svl_BeginMap(TVariant);
    //svl_MapI(svl::TObject);
    //svl_MapP(Value);
  //svl_EndMap;

private:
  //
  void Delete();

private: svl_Except;
  EType type; union
  {
    bool          Bool;
    int           Integer;
    double        Double;
    svl::TString *PString;
    svl::TMem    *PMem;
    TObject      *PObject;
    TPointer     *Pointer;
    TDateTime    *PDateTime;
  }
  value;
};

////////////////////////////////////////////////////////////////////////////////

struct TVariantArray : public TObject , public TArray
{
  void Clear() { TArray::Clear();}
  int  Count() { return TArray::Numb();}
  //
  void Add (TVariant *V,bool EnDelete) { TArray::Add(V,EnDelete);}
  void Link(TVariant &V)               { TArray::Add(&V,false);}
  //
  TVariant &Get(int N) { return *(TVariant*)TArray::Get(N);}
  //
  TVariant &operator [](int       N) { return Get(N);}
  int       operator [](TVariant &V) { return TArray::ObjToN(&V);}
  //
  virtual TObject *New();
  virtual void CopyFrom(TObject *P);
  //
  //svl_BeginMap(TVariantArray);
  //  svl_MapI(svl::TObject);
  //svl_EndMap;
};

////////////////////////////////////////////////////////////////////////////////

class TVariantStack : public TDebug
{
public:
  //
  void Link(TVariant &V);
  //
  int       CountVar()      { return varArray.Count();}
  TVariant &GetVar  (int N) { return varArray[N];}
  //
  void Push();
  bool Pop (); 

private:
  //
  void  NewVarA1FromA2(TVariantArray &A1,TVariantArray &A2);
  void CopyVarA1FromA2(TVariantArray &A1,TVariantArray &A2);

private:
  //
  struct TObject : public svl::TDList_Object
  {
    TVariantArray &LinkVarArray;
    TVariantArray  CopyVarArray;
    //
    TObject(TVariantArray &Link) : LinkVarArray(Link) {}
  };

private: svl_Except;
  TVariantArray varArray;
  TDList        list;
};

////////////////////////////////////////////////////////////////////////////////
}

#endif
